//== SAGITTARIUS ============================================================================

//== FILEDOC =========================================================================

/** @file parser.h
  * @brief The parser
  */

//== BEGINNING OF CODE ===============================================================

#ifndef __SAGUTTARUIS__PARSER__H_
#define __SAGUTTARUIS__PARSER__H_

//== INCLUDES ========================================================================

#include "sagittarius/core/SagittariusCore.h"
#include "sagittarius/parser/pAST.h"
#include "sagittarius/parser/scanner.h"
#include "sagittarius/symtab/symtab.h"
#include <stdarg.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct {
    int dummy;
} parserInfo;

/** @brief Holds data for the parser
 */
typedef struct {
    /// Parser info
    parserInfo pi;
    /// Scanner
    scanner_t* s;
    /// Symbol table
    symtab* st;
    /// Interactive mode
    int intr;
} parser;

/** @brief Emit error message
 */
void parserErr(parser* p, const char* str, ...);
void vparserErr(parser* p, const char* str, va_list v);

/** @brief Constructor
 */
void parserInitBuf(parser* p, constLexBuf buf);

/** @brief Destructor
 */
void parserFinalize(parser* p);

/** @brief Tell if the token matches
 */
int parserMatch(parser* p, uint32 t);

/** @brief Parse source code
 */
sourceFrag* parseSource(parser* p);

/** @brief Parse an import statement
 */
parserExp* parseImportStmt(parser* p);

/** @brief Parse a function definition
 */
functionDef* parseFunDef(parser* p);

/** @brief Parse a parameter list
 */
paramList* parseParamList(parser* p);

/** @brief Parse a parameter
 */
paramListElt parseParam(parser* p);

/** @brief Parse the body of a function
 */
parserExp* parseBasicBody(parser* p, block_info blok);

/** @brief Parse an expression
 */
parserExp* parseExpr(parser* p);

/** @brief Parse a factor
 */
parserExp* parseFactor(parser* p);

/** @brief Parse a feature
 */
parserExp* parseFeature(parser* p, parserExp* lhs);

/** @brief Parse a call
 */
parserExp* parseCall(parser* p, parserExp* e);

/** @brief Parse an lvalue
 */
parserExp* parseLval(parser* p);

/** @brief parseE
 */
parserExp* parseE(parser* p);

/** @brief parseEp
 */
parserExp* parseEp(parser* p);

/** @brief parseT
 */
parserExp* parseT(parser* p);

/** @brief parseTp
 */
parserExp* parseTp(parser* p);

/** @brief parseF
 */
parserExp* parseF(parser* p);

/** @brief parseFp
 */
parserExp* parseFp(parser* p);

/** @brief parseB
 */
parserExp* parseB(parser* p);

/** @brief Parse a symbol
 */
parserExp* parseSymbol(parser* p);

/** @brief Parse an integral value
 */
parserExp* parseIntegral(parser* p);

/** @brief Parse string
 */
parserExp* parseString(parser* p);

/** @brief Parse an rvalue
 */
parserExp* parseRval(parser* p);

#ifdef __cplusplus
}//extern "C"
#endif

#endif
